package net.quanter.ddns4java.providers;

import java.util.ArrayList;
import java.util.List;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.AddDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.AddDomainRecordResponse;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainInfoRequest;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainInfoResponse;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsRequest;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.quanter.ddns4java.DomainRecord;
import net.quanter.ddns4java.Provider;

/**
 * 阿里云DDNS实现
 *
 * @author custer
 */
@Slf4j
public class AliyunProvider implements Provider {
    @Setter
    private String accessKey;
    @Setter
    private String accessSecret;

    private IAcsClient client = null;

    @Override
    public boolean init() {
        if (accessKey == null) {
            log.error("阿里云需要配置accessKey,请在XML的阿里云provider节点下增加accessKey");
            return false;
        }
        if (accessSecret == null) {
            log.error("阿里云需要配置accessSecret,请在XML的阿里云provider节点下增加accessKey");
            return false;
        }
        String regionId = "cn-hangzhou";
        String accessKeyId = accessKey;
        String accessKeySecret = accessSecret;
        try {
            IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            client = new DefaultAcsClient(profile);
            return true;
        } catch (Exception e) {
            log.info("初始化阿里云client错误", e);
            return false;
        }

    }

    @Override
    public boolean hasDomain(String domain) {
        DescribeDomainInfoRequest request = new DescribeDomainInfoRequest();
        request.setDomainName(domain);
        try {
            DescribeDomainInfoResponse response = client.getAcsResponse(request);
            if (response != null) {
                return true;
            }
            return false;
        } catch (ServerException e) {
            serverException("DescribeDomainInfoResponse", e);
            return false;
        } catch (ClientException e) {
            clientException("DescribeDomainInfoResponse", e);
            return false;
        }

    }

    @Override
    public List<DomainRecord> findRecordsByDomain(String domain) {
        DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
        request.setDomainName(domain);
        request.setPageSize(100L);
        List<DomainRecord> domainRecordList = new ArrayList<>();
        try {
            DescribeDomainRecordsResponse response = client.getAcsResponse(request);
            List<DescribeDomainRecordsResponse.Record> recordList = response.getDomainRecords();
            for (DescribeDomainRecordsResponse.Record record : recordList) {
                DomainRecord domainRecord = new DomainRecord(record.getRecordId(), record.getDomainName(),
                    record.getRR(), record.getValue(), record.getType());
                domainRecordList.add(domainRecord);
            }
        } catch (ServerException e) {
            serverException("DescribeDomainRecordsResponse", e);
        } catch (ClientException e) {
            clientException("DescribeDomainRecordsResponse", e);
        }
        return domainRecordList;
    }

    @Override
    public boolean updateRecord(DomainRecord record) {

        UpdateDomainRecordRequest request = new UpdateDomainRecordRequest();
        request.setRecordId(record.getId());
        request.setRR(record.getPrefix());
        request.setType(record.getType().name());
        request.setValue(record.getValue());
        try {
            UpdateDomainRecordResponse response = client.getAcsResponse(request);
            if (response != null && response.getRequestId() != null) {
                return true;
            } else {
                return false;
            }
        } catch (ServerException e) {
            serverException("DescribeDomainRecordsResponse", e);
            return false;
        } catch (ClientException e) {
            clientException("UpdateDomainRecordResponse", e);
            return false;
        }
    }

    @Override
    public boolean insertRecord(DomainRecord insertRecord) {
        AddDomainRecordRequest request = new AddDomainRecordRequest();
        request.setDomainName(insertRecord.getDomain());
        request.setRR(insertRecord.getPrefix());
        request.setType(insertRecord.getType().name());
        request.setValue(insertRecord.getValue());
        try {
            AddDomainRecordResponse response = client.getAcsResponse(request);
            if (response != null && response.getRequestId() != null) {
                return true;
            } else {
                return false;
            }
        } catch (ServerException e) {
            serverException("DescribeDomainRecordsResponse", e);
            return false;
        } catch (ClientException e) {
            clientException("UpdateDomainRecordResponse", e);
            return false;
        }
    }

    private static void serverException(String sdk, ServerException e) {
        log.error("访问阿里云SDK[" + sdk + "]服务端错误:", e);
    }

    private static void clientException(String sdk, ClientException e) {
        log.error("访问阿里云SDK:[{}],客户端错误:", sdk, e.getMessage());
        log.error("ErrCode:{}", e.getErrCode());
        log.error("ErrMsg:{}", e.getErrMsg());
        log.error("RequestId:{}", e.getRequestId());
    }

}
